#include "fig_enemy_boss.h"
#include "fig_player_craft.h"
#include "fig_sounds.h"
#include "fig_pickup_manager.h"
#include "gen_game_state.h"
#include "fig_sfx_manager.h"
#include "fig_gamecenter.h"
#include "fig_vars.h"
#include "fig_constants.h"
#include "fig_boss_attackmove_manager.h"
#include "fig_conversation.h"
#include "fig_sounds.h"
#include "fighter.h"
#include "util/log.h"

#include "ui/ui_progress.h"
#include "num/rand.h"
#include "math/facing.h"
#include "gameflow/game_flow_manager.h"
#include "gameflow/ui_state.h"
#include "gameflow/ui_popup.h"

ui::UIProgress*	FIGEnemyBoss::m_pUIBossHealth = NULL;
ui::UIWidget*	FIGEnemyBoss::m_pUIDecoLeft = NULL;
ui::UIWidget*	FIGEnemyBoss::m_pUIDecoRight = NULL;

FIGEnemyBoss::FIGEnemyBoss(
						   FIGEnemyCraft::ENEMY_TYPES EnemyType
						   ) : 
								FIGTransformEnemy(												
												EnemyType
												),
								m_LevelCompleteCounter(0.0f),
								m_BossState(BOSS_STATE_COMEIN)
{
	
	const float BASE_HP  = (float)FIGConstants::BOSS_BASE_HP;
	const int	CURRENT_LEVEL = ((FIGVars*)FIGVars::Instance())->GetCurrentLevel();
	const int   MAX_LEVEL = FIGConstants::LEVEL_LAST;

	const int TempLife = (int)(BASE_HP + (BASE_HP * ((float)CURRENT_LEVEL / (float)MAX_LEVEL)));
	m_Life = m_MaxLife = (float)TempLife; 
	m_IsBoss = true;
	m_ExplodeSize = 3.0f;
	m_Speed = 0.5f;

	if(!m_pUIBossHealth)
	{
		GENGameState* pState = GENGameState::GetGame();
		m_pUIBossHealth = (ui::UIProgress*)pState->GetWidget("boss_health");
		m_pUIDecoRight = pState->GetWidget("deco_right");
		m_pUIDecoLeft = pState->GetWidget("deco_left");

	}

	m_BossHealthFillCounter.SetLimit(2.5f);
	m_UIAppearCounter.SetLimit(1.0f);
	m_SecondaryWeaponCounter.SetLimit(7.0f);
	m_DelayDie = 2.0f;
	FIGBossAttackMoveManager::Instance().HandleMe(this);
	m_ExplodSoundSfx = FIGSounds::EXPLOSION_VERYBIG;
	
}




void	FIGEnemyBoss::Tick(float dt)
{
	m_GetHitCounter = 0;
	FIGTransformEnemy::Tick(dt);   	

    if(m_LevelCompleteCounter > 0)
	{
		m_LevelCompleteCounter -= dt;
		if(m_LevelCompleteCounter <= 0)
		{
			FIGPlayerCraft::Instance().OnLevelComplete();
		}
	}

	if(m_DelaySpawn > 0)
		return;

	if(m_IsAlive)
	{
		FIGConversation::Instance().UpdateBossPos(m_Pos + math::Vec2(0,m_Radius * 0.5f));		
	}
	else
	{
		
		m_UIAppearCounter.Tick(dt);
		if(m_pUIBossHealth)
		{
			float f = m_UIAppearCounter.GetProgress() * 0.7f;
			if(m_pUIBossHealth)
				m_pUIBossHealth->SetColor(1.0f,1.0f,1.0f, 0.7f - f );
			if(m_pUIDecoRight)
				m_pUIDecoRight->SetColor(1.0f,1.0f,1.0f, 0.7f - f );
			if(m_pUIDecoLeft)
				m_pUIDecoLeft->SetColor(1.0f,1.0f,1.0f, 0.7f - f );
		}
	   return;
	}


	if(m_BossState == BOSS_STATE_COMEIN)
	{
		m_UIAppearCounter.Tick(dt);
		if(m_pUIBossHealth)
			m_pUIBossHealth->SetColor(1.0f,1.0f,1.0f,m_UIAppearCounter.GetProgress() * 0.7f);
		if(m_pUIDecoRight)
			m_pUIDecoRight->SetColor(1.0f,1.0f,1.0f,m_UIAppearCounter.GetProgress() * 0.7f);
		if(m_pUIDecoLeft)
			m_pUIDecoLeft->SetColor(1.0f,1.0f,1.0f,m_UIAppearCounter.GetProgress() * 0.7f);


		if(Tick_ComeIn(dt,m_ComeInStopY))
		{
			NextState();			
			FIGConversation::Instance().StartConvoBossFight(m_ConversationCounter);
		}
		m_bShouldTakeLessDamage = true;
	}
	else if(m_BossState == BOSS_STATE_CONVERSATION)
	{
		MoveAbit(dt,m_ComeInStopY);
		if(m_ConversationCounter > 0)
			m_ConversationCounter -= dt;
		else
		{
			NextState();
			FIGSounds::Instance().PlaySoundSFX(FIGSounds::TRANSOFORMING);
					
		}
	}
	else if(m_BossState == BOSS_STATE_Tranform)
	{
		m_bShouldTakeLessDamage = true;
		MoveAbit(dt,m_ComeInStopY);

		m_BossHealthFillCounter.Tick(dt);
		if(m_pUIBossHealth)
			m_pUIBossHealth->SetProgress(m_BossHealthFillCounter.GetProgress());

		if(m_Bone.TransformForwardTick(dt))
		{
			NextState();
			m_IsReadyToFire = true;
			m_bShouldTakeLessDamage = false;
			
		}
		
	}  	

	else if(m_BossState == BOSS_STATE_ATTACK)
		Tick_Attack(dt);

}

void	FIGEnemyBoss::NextState()
{
	int Temp = (int)m_BossState;
	Temp++;
	m_BossState = (FIGEnemyBoss::BOSS_STATE)Temp;
}

void	FIGEnemyBoss::ReSpawn()
{
	FIGTransformEnemy::ReSpawn();	
	FIGBossAttackMoveManager::Instance().End();
	FIGBossAttackMoveManager::Instance().Clear();

	m_Pos = math::Vec2(0.5f,-0.5f);
	m_BossState = BOSS_STATE_COMEIN; 
	m_ComeInStopY = 0.3f;
	m_Rotation = 0;	
	m_Speed = 0.5f;

	if(m_pUIBossHealth)
	{
		m_pUIBossHealth->SetProgress(0);
		m_pUIBossHealth->SetIsVisible(true);		
	}
	if(m_pUIDecoLeft)
		m_pUIDecoLeft->SetIsVisible(true);
	if(m_pUIDecoRight)
		m_pUIDecoRight->SetIsVisible(true);

	m_BossHealthFillCounter.Reset();
	m_UIAppearCounter.Reset();
	m_DelayDie = 1.5f;
	m_ShootCounter.ForceReady();		// shoot as soon as possible	

    //FIGGameCenter::Instance().UpdateValue(FIGGameCenter::BOSS_KILLER,true,false);

	FIGSounds::Instance().PlaySoundSFX(FIGSounds::BOSS_ARRIVE);
}




void		FIGEnemyBoss::OnDie()
{
	FIGBossAttackMoveManager::Instance().End();
	FIGBossAttackMoveManager::Instance().Clear();
	FIGTransformEnemy::OnDie();
	const float LEVEL_COMPLETE_TIME = 4.0f;
	
	_LOG(MSG_COMMENT, "**** Enemy Boss OnDie ****");

	// now i have decide to give this away as soon as possible
	// normally it is now start at level 2
	FIGVars::Instance()->SetInt(FIGVars::VAR_NAMES_ORB_ALL_GAINED,1);

	FIGPickupManager::Instance().Spawn(FIGPickup::PICKUP_TYPE_1UP,m_Pos);
	m_UIAppearCounter.Reset();
	
	
	if(num::RAND32::Instance().RandInt(0,6) == 0)
		FIGConversation::Instance().PushTalk(FIGConversation::SPEECH_PLAYER_1,"LOC_BINGO");



	if( Fighter::Instance().GetLevel()->IsEndless() == false)
	{
		m_LevelCompleteCounter = LEVEL_COMPLETE_TIME;
		for(int i = 0; i < 10; i++)
			FIGPickupManager::Instance().Spawn(FIGPickup::PICKUP_TYPE_STAR,m_Pos);

		/*
		bool b = FIGGameCenter::Instance()->GetValue(FIGGameCenter::BOSS_KILLER);
		if(b)
			FIGGameCenter::Instance()->UpdateValue(FIGGameCenter::BOSS_KILLER,true,true);

		b = FIGGameCenter::Instance()->GetValue(FIGGameCenter::SUPER_PILOT);
		if(b)
			FIGGameCenter::Instance()->UpdateValue(FIGGameCenter::SUPER_PILOT,true,true);
		*/

		int LevelNum = ((FIGVars*)FIGVars::Instance())->GetCurrentLevel();
		switch(LevelNum)
		{
		case 1:  
				FIGGameCenter::Instance().UpdateValue(FIGGameCenter::BOSS_KILLER,true,true);
			break;
		case 2:
				FIGGameCenter::Instance().UpdateValue(FIGGameCenter::VERTERN,true,true);
			break;
		case 3:
				FIGGameCenter::Instance().UpdateValue(FIGGameCenter::SUPER_PILOT,true,true);
			break;
		case 4:
				FIGGameCenter::Instance().UpdateValue(FIGGameCenter::ALIEN_CRUSHER,true,true);
			break;
		case 5:
				FIGGameCenter::Instance().UpdateValue(FIGGameCenter::SENIOR_ALIEN_CRUSHER,true,true);
			break;
		case 6:
				FIGGameCenter::Instance().UpdateValue(FIGGameCenter::ALIEN_CRUSHER_ULTIMATE,true,true);
			break;
		case 7:
				FIGGameCenter::Instance().UpdateValue(FIGGameCenter::ZEALOUS_PILOT,true,true);
			break;
		}
        
        
        //testing
        //for(int i = 0; i < FIGGameCenter::ACHIEVEMENT_C; i++)
        //    FIGGameCenter::Instance().UpdateValue(FIGGameCenter::ACHIEVEMENT_TYPE(i),true,true);
            
		/*
		if(LevelNum == FIGConstants::LEVEL_LAST)
		{
			int Difficulty = FIGVars::Instance()->GetInt( FIGVars::VAR_NAMES_DIFFICULTY);
			switch(Difficulty)
			{
			case 0:
				FIGGameCenter::Instance()->UpdateValue(FIGGameCenter::ALIEN_CRUSHER,true,true);
				break;
			case 1:
				FIGGameCenter::Instance()->UpdateValue(FIGGameCenter::SENIOR_ALIEN_CRUSHER,true,true);
				break;
			case 2:
				FIGGameCenter::Instance()->UpdateValue(FIGGameCenter::ALIEN_CRUSHER_ULTIMATE,true,true);
				break;
			};
		
		}
		*/
	}


	// disable it for now
	//FIGUIGeneralInfo* pPopup = (FIGUIGeneralInfo*)gameflow::UIPopupManager::Instance().GetPopup("ui/general_info.ui");
	//pPopup->ShowThis("Unlocked 123",0.1f);
	
}


void		FIGEnemyBoss::Tick_Attack(float dt)
{
	FIGBossAttackMoveManager::Instance().Tick(dt);

	if(!FIGBossAttackMoveManager::Instance().ShouldDisableOtherMovement())
	{
		MoveAbit(dt, m_ComeInStopY);	
	}
	

	m_IsReadyToFire = true;
	if(FIGBossAttackMoveManager::Instance().ShouldDisableAttack())	
	{
		
		m_IsReadyToFire = false;
	}
	else
	{
		m_SecondaryWeaponCounter.Tick(dt);

		if(m_SecondaryWeaponCounter.IsReady())
		{
			m_SecondaryWeaponCounter.Reset();
			OnSecondaryWeaponShoot();
		}
	}

		
	
}

void		FIGEnemyBoss::GotDamage(float Amount,FIGBullet* pBullet, bool Force)
{

	// testing 
	// Amount = 100000;

	if(m_Life < 0)
		return;

	if(!Force && m_bShouldTakeLessDamage)
		Amount = Amount * 0.005f;

	float BackupLife = m_Life;

 	FIGTransformEnemy::GotDamage(Amount,pBullet, Force);

	if(m_pUIBossHealth)
		m_pUIBossHealth->SetProgress( m_Life / (m_MaxLife+ m_ExtraLife));

	
	float HalfLife = (m_MaxLife + m_ExtraLife) * 0.5f;

	// transformback and godown 
	if(BackupLife > HalfLife && m_Life < HalfLife)
	{
		if(
			num::RAND32::Instance().RandInt(0,1) == 0 && 
			CanTransformBackAttack()
			)	
			FIGBossAttackMoveManager::Instance().Start(
									FIGBossAttackMoveManager::ATTACK_MOVEMENT_GODOWN_SPEEDLY, 
									0.0f);
	}
	

	
}

void		FIGEnemyBoss::OnStartDying()
{
	FIGSfx* pSFX = NULL;

	/*pSFX = FIGSFXManager::Instance().Spawn(
									FIGSfx::EXPLODING_TYPE_EXPLODEBANG,
									m_Pos,
									2.0f);
	if(pSFX)
	{
		AddSFX(pSFX);			
		pSFX->SetIsRenderByOwner(true);
	}*/

	pSFX = FIGSFXManager::Instance().Spawn(
									FIGSfx::EXPLODING_VERYBIG,
									m_Pos,
									2.0f);
	if(pSFX)
	{
		AddSFX(pSFX);			
		pSFX->SetIsRenderByOwner(true);
	}
	

	m_BossState = BOSS_STATE_DYING;
	m_IsReadyToFire = false;
	
	for(int i = 1; i < m_Bone.GetBonePartCount(); i++)
	{
		FIGBonePart* pBonePart = m_Bone.GetBonePartByID(i);
		math::Vec2 P = pBonePart->GetPosBackup();

		if(P.x != 0 && P.y != 0)
		{
			/*pSFX = FIGSFXManager::Instance().Spawn(
										FIGSfx::EXPLODING_TYPE_EXPLODEBANG,
										m_Pos + P,
										num::RAND32::Instance().RandFloat(0.5f,1.0f)
										);  
			if(pSFX)
			{
				AddSFX(pSFX);			
				pSFX->SetIsRenderByOwner(true);
			}*/

			pSFX = FIGSFXManager::Instance().Spawn(
										FIGSfx::EXPLODING_VERYBIG,
										m_Pos + P,
										num::RAND32::Instance().RandFloat(0.5f,1.0f)
										);  
			if(pSFX)
			{
				AddSFX(pSFX);			
				pSFX->SetIsRenderByOwner(true);
			}
		}
		
	}
}


